﻿using OpenTK.Graphics;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using LightCAD.Three;
using EventArgs = System.EventArgs;
using OpenTK;
using LightCAD.Three.OpenGL;
using Microsoft.CodeAnalysis;
using OpenTK.Graphics.Wgl;
using System.Runtime.InteropServices;
using System.Security;
using System.Runtime.InteropServices.JavaScript;
using Avalonia.Controls;

namespace TestWinform
{
    public partial class ThreeTestForm : Form
    {
        private GLControl glControl;
        private WebGLRenderer renderer;
        private PerspectiveCamera camera;
        private Scene scene;
        private Mesh mesh;
        private BoxGeometry geometry;
        private RenderCanvas canvas;
        private OrbitControls controls;
        public ThreeTestForm()
        {
            InitializeComponent();
            this.glControl = new GLControl();

            this.glControl.VSync = false;
            this.Controls.Add(this.glControl);
            this.glControl.Dock = DockStyle.Fill;
            this.Load += ThreeTestForm_Load;
            this.Closing += ThreeTestForm_Closing; ;
            this.WindowState = FormWindowState.Maximized;
            //glControl.Run();
            Application.Idle += Application_Idle;
        }
        private bool isLoad = false;
        //[SuppressUnmanagedCodeSecurity]
        //[DllImport("OPENGL32.DLL", EntryPoint = "wglGetProcAddress", ExactSpelling = true, SetLastError = true)]
        //internal extern static IntPtr GetProcAddress(String lpszProc);
        [SuppressUnmanagedCodeSecurity]
        [DllImport("OPENGL32.DLL", EntryPoint = "wglGetProcAddress", ExactSpelling = true, SetLastError = true)]
        internal extern static IntPtr GetProcAddress(IntPtr lpszProc);

        private void ThreeTestForm_Load(object? sender, EventArgs e)
        {
            var context = GraphicsContext.CurrentContext;
            gl.GetAddressFunc = (fn) =>
            {
                var context_internal = context as IGraphicsContextInternal;
                var ptr = context_internal.GetAddress(fn);
                return ptr;
            };


            init();
            Resize();
            this.SizeChanged += ThreeTestForm_SizeChanged;
            isLoad = true;
        }
        private void init()
        {
            this.scene = new Scene();
            var ambientLight = new AmbientLight(0xcccccc, 0.4);
            scene.add(ambientLight);

            var dirLight = new DirectionalLight(0xffffff, 0.8);
            dirLight.position.Set(1, 2, 3);
            scene.add(dirLight);

            this.geometry = new BoxGeometry(200, 200, 200);
            //var material = new MeshBasicMaterial(new MaterialValues { color = new LightCAD.Three.Color(0xff0000) });
            var material = new MeshPhongMaterial{ color = new Color(0xff0000), side = Constants.DoubleSide };//map = map,

            this.mesh = new Mesh(geometry, material);
            this.scene.add(this.mesh);
            var ratio = glControl.Width / glControl.Height;
            camera = new PerspectiveCamera(70, ratio, 1, 1000);
            camera.position.Z = 400;

            this.canvas = new RenderCanvas().Set(glControl.Width, glControl.Height);
            this.renderer = new WebGLRenderer(canvas);
            //renderer.setSize(glControl.Width, glControl.Height);
            controls = new OrbitControls(camera, glControl);
            controls.screenSpacePanning = true;

        }
        private void Application_Idle(object? sender, EventArgs e)
        {
            this.glControl.MakeCurrent();
            Animate();
            this.glControl.SwapBuffers();
        }
        private void Animate()
        {
            if (!isLoad)
                return;
            this.renderer.setClearColor(0x00FF00);
            this.renderer.render(this.scene, camera);
        }

        private void ThreeTestForm_SizeChanged(object? sender, EventArgs e)
        {
            Resize();
        }
        private void Resize()
        {
            this.camera.aspect = this.Width / (float)this.Height;
            camera.updateProjectionMatrix();
            glControl.Width = this.Width;
            glControl.Height = this.Height;
            this.canvas.Set(glControl.Width, glControl.Height);
            this.renderer.setViewport(0, 0, glControl.Width, glControl.Height);
        }

        private void ThreeTestForm_Closing(object? sender, CancelEventArgs e)
        {
        }


    }
}
